/*
 * axios网络请求全局初始化配置
 * <p>
 * 这里直接使用axios库提供的默认实例对象(不再创建新的实例对象，若开发者需要多个实例，请自行创建)
 * </p>
 * @Author: bobo
 * @Date: 2021-01-04 17:34:17
 * 
 * GET请求:params 相当于query URLparameters
 * POST请求: data:相当于json实体或表单(当为表单时需要特殊处理)
 * 
 */
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import login from '@/api/login-api'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.baseURL = process.env.VUE_APP_BASE_URL
axios.defaults.timeout = 10000
axios.defaults.withCredentials = true
/**
 * 将axios实例对象，绑定到Vue中，便于在vue中使用
 * .vue文件中可通过this.axios获取该实例
 */
if (process.env.NODE_ENV === 'development') {
  //开发环境下使用vue-axios,有代码提示,便于开发
  Vue.use(VueAxios, axios)
} else {
  Vue.prototype.axios = axios;
}

// ----------------------------------------------------------------------------
// *******************************全局前置拦截器配置:******************************
/**
 * 全局access_token处理
 * 1.这里统一拦截axios请求中headers对象中的【NeedToken:true】参数
 */
axios.interceptors.request.use(request => {
  let _needToken = true;
  if (request.headers.NeedToken != undefined) {
    _needToken = request.headers.NeedToken;
  }
  if (_needToken) {
    return new Promise(resolve => {
      login.getAccessToken().then(token => {
        request.params.access_token = token
        resolve(request)
      });
    });
  } else {
    return request;
  }
}, err => {
  return Promise.reject(err);
})

// *******************************全局后置拦截器配置:******************************
/**
 * 请求响应结果统一转换拦截器
 */
axios.interceptors.response.use(res => {
  if (res.status >= 200 || res.status < 300) {
    return Promise.resolve(res.data);
  } else {
    return Promise.resolve({
      errcode: res.status,
      errmsg: "Http请求状态码异常"
    })
  }
}, err => {
  // 请求响应异常，最终会回调到catch中
  return Promise.reject(err);
})
//请求取消数组
const cancelRequestMap = new Map();
export default {
  /**
   * GET 请求
   * @param  url 请求地址
   * @param  config 请求配置，url参数对象为config.params
   * @param  mockdata 模拟数据
   * @returns 
   */
  get(url, config, mockdata) {
    return this.request(url, 'get', {}, config, mockdata)
  },
  /**
   * POST 请求
   * @param  url 请求地址
   * q@param data body数据，默认json格式
   * @param  config 请求配置，url参数对象为config.params
   * @param  mockdata 模拟数据
   * @param isForm true 表单提交，false json提交
   * @returns 
   */
  post(url, data, config, mockdata, isForm = false) {
    if (isForm) {
      var qs = require('qs');
      data = qs.stringify(data);
    }
    return this.request(url, 'post', data, config, mockdata)
  },
  /**
   * Delete 请求
   * @param  url 请求地址
   * @param  config 请求配置，url参数对象为config.params
   * @param  mockdata 模拟数据
   * @returns 
   */
  delete(url, config, mockdata) {
    return this.request(url, 'delete', {}, config, mockdata);
  },
  /**
   * 取消某个请求
   * @param  url 请求路径
   */
  cancel(url) {
    var cancel = cancelRequestMap.get(url);
    if (cancel) {
      cancel(`主动取消请求=>${url}`)
    }
  },
  /**
   * 请求封装(支持mock-data)
   * <p>
   * 模拟数据响应时，不走网络
   * </p>
   * @param  promiste 实际网络请求
   * @param  mockdata  模拟数据
   */
  request(url, method, data, config, mockdata, timeout = 2000) {
    const isMock = mockdata && process.env.VUE_APP_MOCK === 'true';
    if (isMock) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(mockdata);
        }, timeout);
      });
    }
    if (config == null) {
      config = {}
    }
    if (config.params == undefined || config.params == null) {
      config.params = {}
    }
    return axios.request({
      ...config,
      data: data,
      method: method,
      url: url,
      cancelToken: new axios.CancelToken(function (cancel) {
        //将待取消的请求放入字典中
        cancelRequestMap.set(url, cancel)
      }),
    }).finally(() => {
      cancelRequestMap.delete(url)
    })
  }
}